using System;
using System.Collections.Generic;
using System.Threading;
using GraphLib;
using ctem.kernel.logger;
using MCSharp;
using System.Runtime.Serialization;
using System.Runtime.Remoting.Messaging;

namespace    ctem.kernel
{
 using System;
using MCSharp;
using System.Threading;
using System.Runtime.Serialization;
using System.Runtime.Remoting.Messaging;

[Serializable()]
public  partial class ModelExecutor : ISerializable {

 //-------------- MCsharp functions -----------

 public ModelExecutor ( ) {
  mcsharp_initiate();
}

 public ModelExecutor ( SerializationInfo info, StreamingContext context ) {
  MCSharp.Serialization.UnPack ( info, context, this );
   }

 public void GetObjectData ( SerializationInfo info, StreamingContext context ) {
  MCSharp.Serialization.Pack ( info, context, this );
 }

 public void mcsharp_initiate ( ) {

  Monitor.Enter ( CommExec.Objects );
  int mcObjectNumber = CommExec.Objects.Count + 1;
  CommExec.Objects.Add ( mcObjectNumber, this );
  Monitor.Exit ( CommExec.Objects );

  UnLocked = new MCSharp.channel ( this, mcObjectNumber, "mcsharpChannelUnLocked" );
  mcsharpQueueWaitForUnLock = new MCSharp.ThreadQ();

  WaitForUnLock = new MCSharp.handler ( this, mcObjectNumber, "mcsharpHandlerWaitForUnLock" );
  Locked = new MCSharp.channel ( this, mcObjectNumber, "mcsharpChannelLocked" );
  mcsharpQueueWaitForLock = new MCSharp.ThreadQ();

  WaitForLock = new MCSharp.handler ( this, mcObjectNumber, "mcsharpHandlerWaitForLock" );
  EndModelling = new MCSharp.channel ( this, mcObjectNumber, "mcsharpChannelEndModelling" );
  mcsharpQueueWaitForEndModelling = new MCSharp.ThreadQ();

  WaitForEndModelling = new MCSharp.handler ( this, mcObjectNumber, "mcsharpHandlerWaitForEndModelling" );
 }

public ModelExecutorState state = ModelExecutorState.Initialized  ;

 const int maxspeed = 95  ;

 public int speed = 95  ;

 public long end_time = Int32.MaxValue  ;

 bool online = true  ;

 bool command_to_lock = false  ;

 object anchor = new object( )  ;

 ILogger logger ;

 public  ModelExecutor (  ILogger logger )  {

   mcsharp_initiate();

    this.logger  = logger  ;
 BUG_in_MCSCreateGraph( )  ;
 state  = ModelExecutorState.Created  ;


 }

  private class McsharpPrivateClassStart {

   ModelExecutor parent;

   public McsharpPrivateClassStart ( ModelExecutor parent
              ) {
    this.parent = parent;
   }

   public void run() {

   MCSharp.ThreadManager.SetThreadAffinityMask();

    parent.mcsharpStartBody (  );

   }
  }

  private void mcsharpStartBody (

              )
 {
   state  = ModelExecutorState.Working  ;
 logger.WriteMessage( MessagePriority.Info  , "We started; ModelExecutorState= " + state  )  ;
 while ( ( state  == ModelExecutorState.Working   )  && ( Timer.GetCurrentTime( )  != end_time   )   )
  {
   lock ( anchor   )  {
   if ( command_to_lock   )
    {
   Locked.Send ( new object[] {   } )
  ;
 logger.WriteMessage( MessagePriority.Debug  , "locked"  )  ;
 WaitForUnLock  .Get(new object[]{ } )
;
 logger.WriteMessage( MessagePriority.Debug  , "unlocked"  )  ;
 }

  }
 Timer.Fire( )  ;
 foreach ( IActor actor in sorted_actors  )  {
   actor.Fire( (double)Timer.GetStep( )  )  ;
 }
 if ( online   )
   Thread.Sleep( maxspeed / speed  )  ;

  sorted_actors  = this.graph.TopologSort( )  ;
 }

  if ( ( state  == ModelExecutorState.Terminated   )  || ( state  == ModelExecutorState.Stoped   )   )
    {
   logger.WriteMessage( MessagePriority.Info  , "We terminate or stop modelling, ModelExecutorState==" + state  )  ;
 EndModelling.Send ( new object[] {   } )
  ;
 }

  else
  {
   foreach ( IActor actor in sorted_actors  )  {
   actor.OnStopModelling( )  ;
 }
 state  = ModelExecutorState.Stoped  ;
 }
 
 }




  public  void Start (  ) {
   McsharpPrivateClassStart prclassobject = new McsharpPrivateClassStart ( this );
   ThreadStart tstart = new ThreadStart ( prclassobject.run );
   ( new Thread ( tstart ) ).Start();
  }
public  void Lock (  )   {
   lock ( anchor   )  {
   command_to_lock  = true  ;
 }
 WaitForLock  .Get(new object[]{ } )
;
 }
public  void UnLock (  )   {
   UnLocked.Send ( new object[] {   } )
  ;
 }
public  void Terminate (  )   {
   if ( ( state  == ModelExecutorState.Locked   )  || ( state  == ModelExecutorState.TemporaryStoped   )  || ( state  == ModelExecutorState.Stoped   )   )
   UnLock( )  ;

  if ( state  == ModelExecutorState.Working   )
    {
   state  = ModelExecutorState.Terminated  ;
 WaitForEndModelling  .Get(new object[]{ } )
;
 }

  state  = ModelExecutorState.Terminated  ;
 logger.WriteMessage( MessagePriority.Debug  , "TopologSort Started"  )  ;
 sorted_actors  = this.graph.TopologSort( )  ;
 logger.WriteMessage( MessagePriority.Debug  , "TopologSort Ended"  )  ;
 foreach ( IActor actor in sorted_actors  )  {
   Console.WriteLine( "Terminate " + ( (INameable)actor   ).GetName( )  )  ;
 actor.Dispose( )  ;
 }
 logger.WriteMessage( MessagePriority.Info  , "We termitated; Actors are disposed; ModelExecutorState= " + state  )  ;
 }
public  void Stop (  )   {
   if ( ( state  == ModelExecutorState.Locked   )  || ( state  == ModelExecutorState.TemporaryStoped   )   )
   UnLock( )  ;

  state  = ModelExecutorState.Stoped  ;
 WaitForEndModelling  .Get(new object[]{ } )
;
 logger.WriteMessage( MessagePriority.Debug  , "TopologSort Started"  )  ;
 sorted_actors  = this.graph.TopologSort( )  ;
 logger.WriteMessage( MessagePriority.Debug  , "TopologSort Ended"  )  ;
 foreach ( IActor actor in sorted_actors  )  {
   actor.OnStopModelling( )  ;
 }
 logger.WriteMessage( MessagePriority.Info  , "We stoped; ModelExecutorState= " + state  )  ;
 state  = ModelExecutorState.Created  ;
 }
public  void TemporaryStop (  )   {
   Lock( )  ;
 logger.WriteMessage( MessagePriority.Debug  , "TopologSort Started"  )  ;
 sorted_actors  = this.graph.TopologSort( )  ;
 logger.WriteMessage( MessagePriority.Debug  , "TopologSort Ended"  )  ;
 foreach ( IActor actor in sorted_actors  )  {
   actor.TemporaryStop( )  ;
 }
 state  = ModelExecutorState.TemporaryStoped  ;
 logger.WriteMessage( MessagePriority.Info  , "We temporary stoped; ModelExecutorState= " + state  )  ;
 }
public  void RunAfterTemporaryStop (  )   {
   UnLock( )  ;
 logger.WriteMessage( MessagePriority.Info  , "We RunAfterTemporaryStop; ModelExecutorState= " + state  )  ;
 }
private  void Init (  )   {
   Timer.ReInitialize( )  ;
 foreach ( IActor actor in sorted_actors  )  {
   Console.WriteLine( "ReInitialize " + ( (INameable)actor   ).GetName( )  )  ;
 actor.ReInitialize( )  ;
 }
 state  = ModelExecutorState.Initialized  ;
 logger.WriteMessage( MessagePriority.Info  , "We reinitialized; ModelExecutorState= " + state  )  ;
 }
private  void SortGraph (  )   {
   logger.WriteMessage( MessagePriority.Debug  , "TopologSort Started"  )  ;
 sorted_actors  = this.graph.TopologSort( )  ;
 logger.WriteMessage( MessagePriority.Debug  , "TopologSort Ended"  )  ;
 }
public  void OfflineModeBegin (  )   {
   SortGraph( )  ;
 online  = false  ;
 foreach ( IActor actor in sorted_actors  )  {
   Console.WriteLine( "To offline mode " + ( (INameable)actor   ).GetName( )  )  ;
 actor.OnOfflineModeSet( end_time  )  ;
 }
 Init( )  ;
 }
public  void OnlineModeBegin (  )   {
   SortGraph( )  ;
 online  = true  ;
 foreach ( IActor actor in sorted_actors  )  {
   Console.WriteLine( "To online mode " + ( (INameable)actor   ).GetName( )  )  ;
 actor.OnOnlineModeSet( )  ;
 }
 Init( )  ;
 }

 //-------------Channel declarations-----------------

  public MCSharp.channel UnLocked;

 //-------------Handler declaration-----------------

    public MCSharp.handler WaitForUnLock;


 //-------------Queues------------------------------

 [NonSerialized] private MCSharp.ThreadQ mcsharpQueueWaitForUnLock;


 //-------------Masks--------------------------------

 private const int mcsharp_mask_WaitForUnLock = 1 << 0;
 private const int mcsharp_mask_UnLocked = 1 << 1;
 private const int mcsharp_mask_WaitForUnLockUnLocked =
            mcsharp_mask_WaitForUnLock
          | mcsharp_mask_UnLocked;
 [NonSerialized] private MCSharp.BitMask mcsharpBitMaskWaitForUnLockUnLocked = new MCSharp.BitMask();

 private void scanWaitForUnLockUnLocked () {
  if ( mcsharpBitMaskWaitForUnLockUnLocked.match
        ( mcsharp_mask_WaitForUnLockUnLocked ) )
   mcsharpQueueWaitForUnLock.wakeup();
 }


[OneWay]
public void mcsharpChannelUnLocked (  )  {
   lock ( mcsharpQueueWaitForUnLock ) {
    UnLocked.Enqueue ( new object [] {  } );
    if ( ! mcsharpBitMaskWaitForUnLockUnLocked.match
          ( mcsharp_mask_UnLocked ) )   {
     mcsharpBitMaskWaitForUnLockUnLocked.set ( mcsharp_mask_UnLocked );
     scanWaitForUnLockUnLocked ();
    }
   }
 }

 public void mcsharpHandlerWaitForUnLock (  )   {
  Monitor.Enter ( mcsharpQueueWaitForUnLock );
  if ( ! mcsharpBitMaskWaitForUnLockUnLocked.match ( mcsharp_mask_WaitForUnLock ) ) goto now;
  later:
   mcsharpQueueWaitForUnLock.yield ( mcsharpQueueWaitForUnLock );
   if ( mcsharpQueueWaitForUnLock.empty )
    mcsharpBitMaskWaitForUnLockUnLocked.clear ( mcsharp_mask_WaitForUnLock );
  now:
   if ( mcsharpBitMaskWaitForUnLockUnLocked.match ( 
    mcsharp_mask_UnLocked ) )   {
    object[] oUnLocked = ( object[] ) UnLocked.Dequeue();
    if ( UnLocked.Count == 0 )
         mcsharpBitMaskWaitForUnLockUnLocked.clear ( mcsharp_mask_UnLocked );
    scanWaitForUnLockUnLocked ();
    Monitor.Exit ( mcsharpQueueWaitForUnLock );
     {
   command_to_lock  = false  ;
 state  = ModelExecutorState.Working  ;
 }
   }
   else {
    mcsharpBitMaskWaitForUnLockUnLocked.set ( mcsharp_mask_WaitForUnLock );
    goto later;
  }

 }

 //-------------Channel declarations-----------------

  public MCSharp.channel Locked;

 //-------------Handler declaration-----------------

    public MCSharp.handler WaitForLock;


 //-------------Queues------------------------------

 [NonSerialized] private MCSharp.ThreadQ mcsharpQueueWaitForLock;


 //-------------Masks--------------------------------

 private const int mcsharp_mask_WaitForLock = 1 << 0;
 private const int mcsharp_mask_Locked = 1 << 1;
 private const int mcsharp_mask_WaitForLockLocked =
            mcsharp_mask_WaitForLock
          | mcsharp_mask_Locked;
 [NonSerialized] private MCSharp.BitMask mcsharpBitMaskWaitForLockLocked = new MCSharp.BitMask();

 private void scanWaitForLockLocked () {
  if ( mcsharpBitMaskWaitForLockLocked.match
        ( mcsharp_mask_WaitForLockLocked ) )
   mcsharpQueueWaitForLock.wakeup();
 }


[OneWay]
public void mcsharpChannelLocked (  )  {
   lock ( mcsharpQueueWaitForLock ) {
    Locked.Enqueue ( new object [] {  } );
    if ( ! mcsharpBitMaskWaitForLockLocked.match
          ( mcsharp_mask_Locked ) )   {
     mcsharpBitMaskWaitForLockLocked.set ( mcsharp_mask_Locked );
     scanWaitForLockLocked ();
    }
   }
 }

 public void mcsharpHandlerWaitForLock (  )   {
  Monitor.Enter ( mcsharpQueueWaitForLock );
  if ( ! mcsharpBitMaskWaitForLockLocked.match ( mcsharp_mask_WaitForLock ) ) goto now;
  later:
   mcsharpQueueWaitForLock.yield ( mcsharpQueueWaitForLock );
   if ( mcsharpQueueWaitForLock.empty )
    mcsharpBitMaskWaitForLockLocked.clear ( mcsharp_mask_WaitForLock );
  now:
   if ( mcsharpBitMaskWaitForLockLocked.match ( 
    mcsharp_mask_Locked ) )   {
    object[] oLocked = ( object[] ) Locked.Dequeue();
    if ( Locked.Count == 0 )
         mcsharpBitMaskWaitForLockLocked.clear ( mcsharp_mask_Locked );
    scanWaitForLockLocked ();
    Monitor.Exit ( mcsharpQueueWaitForLock );
     {
   state  = ModelExecutorState.Locked  ;
 }
   }
   else {
    mcsharpBitMaskWaitForLockLocked.set ( mcsharp_mask_WaitForLock );
    goto later;
  }

 }

 //-------------Channel declarations-----------------

  public MCSharp.channel EndModelling;

 //-------------Handler declaration-----------------

    public MCSharp.handler WaitForEndModelling;


 //-------------Queues------------------------------

 [NonSerialized] private MCSharp.ThreadQ mcsharpQueueWaitForEndModelling;


 //-------------Masks--------------------------------

 private const int mcsharp_mask_WaitForEndModelling = 1 << 0;
 private const int mcsharp_mask_EndModelling = 1 << 1;
 private const int mcsharp_mask_WaitForEndModellingEndModelling =
            mcsharp_mask_WaitForEndModelling
          | mcsharp_mask_EndModelling;
 [NonSerialized] private MCSharp.BitMask mcsharpBitMaskWaitForEndModellingEndModelling = new MCSharp.BitMask();

 private void scanWaitForEndModellingEndModelling () {
  if ( mcsharpBitMaskWaitForEndModellingEndModelling.match
        ( mcsharp_mask_WaitForEndModellingEndModelling ) )
   mcsharpQueueWaitForEndModelling.wakeup();
 }


[OneWay]
public void mcsharpChannelEndModelling (  )  {
   lock ( mcsharpQueueWaitForEndModelling ) {
    EndModelling.Enqueue ( new object [] {  } );
    if ( ! mcsharpBitMaskWaitForEndModellingEndModelling.match
          ( mcsharp_mask_EndModelling ) )   {
     mcsharpBitMaskWaitForEndModellingEndModelling.set ( mcsharp_mask_EndModelling );
     scanWaitForEndModellingEndModelling ();
    }
   }
 }

 public void mcsharpHandlerWaitForEndModelling (  )   {
  Monitor.Enter ( mcsharpQueueWaitForEndModelling );
  if ( ! mcsharpBitMaskWaitForEndModellingEndModelling.match ( mcsharp_mask_WaitForEndModelling ) ) goto now;
  later:
   mcsharpQueueWaitForEndModelling.yield ( mcsharpQueueWaitForEndModelling );
   if ( mcsharpQueueWaitForEndModelling.empty )
    mcsharpBitMaskWaitForEndModellingEndModelling.clear ( mcsharp_mask_WaitForEndModelling );
  now:
   if ( mcsharpBitMaskWaitForEndModellingEndModelling.match ( 
    mcsharp_mask_EndModelling ) )   {
    object[] oEndModelling = ( object[] ) EndModelling.Dequeue();
    if ( EndModelling.Count == 0 )
         mcsharpBitMaskWaitForEndModellingEndModelling.clear ( mcsharp_mask_EndModelling );
    scanWaitForEndModellingEndModelling ();
    Monitor.Exit ( mcsharpQueueWaitForEndModelling );
     {
   }
   }
   else {
    mcsharpBitMaskWaitForEndModellingEndModelling.set ( mcsharp_mask_WaitForEndModelling );
    goto later;
  }

 }
}


}